﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using Domain.Model;

using Facade.Manager;

using Presentation.Models;
using Presentation.Models.Binders;

namespace Presentation.Controllers
{
    public class ProjectController : AbstractController
    {
        public ProjectController()
            : base()
        { }

        //
        // GET: /Project/

        public ActionResult Index()
        {
            return RedirectToAction("All");
        }

        //
        // GET: /Project/Create
        [Authorize(Roles = "admins")]
        public ActionResult Create(int programId)
        {
            var project = new Project();
            
            var form = formManager.GetProjectForm();

            CreateProjectDetails(project, form);

            var model = new ProjectViewModel
            {
                ProgramId = programId,
                Project = project,
                Form = form
            };

            return View(model);
        }

        //
        // POST: /Project/Create //Salman has edited the code here for validation
        [HttpPost]
        public ActionResult Create([ModelBinder(typeof(ProjectViewModelBinding))] ProjectViewModel model)
        {
            int programId = model.ProgramId;
            if (!ValidateInput(model, formManager.GetProjectForm()))
            {
                model.Form = formManager.GetProjectForm();
                return View(model);
            }
            if (programId > 0)
                programManager.AddProject(model.ProgramId, model.Project);
            else portfolioManager.AddStandAloneProject(model.Project);

            return RedirectToAction("Index", "Portfolio");
        }
        //Function to validate inputs
        public static bool ValidateInput(ProjectViewModel model, Form form)
        {
            for (int i = 0; i < model.Project.Details.Count; i++)
            {
                try
                {
                    if (model.Project.Details[i].Value == null)
                    {
                        var errmsg = "*A field can not be empty.";
                        model.errmsg = errmsg;
                        model.errindex = i;
                        return false;
                    }
                    else if (form.FormElements[i].Type.Equals("typeChar"))
                    {
                        //checking if value entered is text.
                        try
                        {
                            double d;
                            d = System.Double.Parse(model.Project.Details[i].Value);
                            var errmsg = "*Numeric value is not acceptable in a text field.";
                            model.errmsg = errmsg;
                            model.errindex = i;
                            return false;
                        }
                        catch (Exception e)//parsing isn't successful no action is required.
                        {                        
                        }
                    }
                    else if (form.FormElements[i].Type.Equals("typeNumeric"))
                    {
                        //checking if value entered is Numeric.
                        try
                        {
                            double d;
                            d = System.Double.Parse(model.Project.Details[i].Value);                            
                        }
                        catch (Exception e)
                        {
                            var errmsg = "*Text value is not acceptable in a numeric field.";
                            model.errmsg = errmsg;
                            model.errindex = i;
                            return false;
                        }
                    }
                    else if (form.FormElements[i].Type.Equals("typeDate"))
                    {
                        //checking if value entered is a Date.
                        try
                        {
                            short res = IsDate(model.Project.Details[i].Value);
                            var errmsg = "";
                            if (res != 0) //if it is a valid date, res will hold 0
                            {                               
                                if (res == 1)//if date is an older fied, res will hold 1
                                    errmsg = "*Date can not be an older date";
                                else //if date is in invalid format, res will hold 2
                                    errmsg = "*Please enter a valid date in Date field e.g. DD/MM/YYYY";
                                model.errmsg = errmsg;
                                model.errindex = i;
                                return false;
                            }
                        }
                        catch (Exception e)
                        {                            
                        }
                    }
                   
                }
                catch (Exception e)
                { 
                }
            }
            return true;
        }
        //this function is for ensuring if valid date is entered. added by salman
        public static short IsDate(Object obj)
        {
            string strDate = obj.ToString();
            short res = 0;
            try
            {//esuring that it is not an old date.
                DateTime dt = DateTime.Parse(strDate);
                if (dt.Year < System.DateTime.Now.Year)
                    res = 1;
                else if (dt.Year == System.DateTime.Now.Year)
                {
                    if (dt.Month < System.DateTime.Now.Month)
                        res = 1;
                    else if (dt.Month == System.DateTime.Now.Month)
                    {
                        if (dt.Day < System.DateTime.Now.Day)
                            res = 1;
                        else
                            res = 0;//success
                    }
                    else
                        res = 0;//success
                }
                else
                    res = 0;//success
            }
            catch
            {                
                res = 2;
            }
            return res;
        }

        //
        // GET: /Project/Delete/
        [Authorize(Roles = "admins")]
        public ActionResult Delete(int id, int programId)
        {
            var project = projectManager.GetProjectById(id);

            if (project != null)
            {
                projectManager.DeleteProject(project);

                if (programId > 0)
                    return RedirectToAction("Edit", "Program", new { id = programId });
                else return RedirectToAction("Index", "Portfolio");
            }
            else return RedirectToAction("Error");
            
        }

        //
        // GET: /Project/Details/

        public ActionResult Details(int id)
        {
            return View(projectManager.GetProjectById(id));
        }

        //
        // GET: /Project/View/

        public ActionResult View(int id)
        {
            var model = CreateViewModel(id);

            CreateProjectDetails(model.Project, model.Form);

            return View(model);
        }

        // GET: /Project/Edit
        [Authorize(Roles = "admins")]
        public ActionResult Edit(int id)
        {
            var model = CreateViewModel(id);

            CreateProjectDetails(model.Project, model.Form);

            return View(model);
        }

        // POST: /Project/Edit
        [HttpPost]
        public ActionResult Edit([ModelBinder(typeof(ProjectViewModelBinding))] ProjectViewModel model)
        {
            if (model.Project != null)
            {
                if (!ValidateInput(model, formManager.GetProjectForm())) //validating input in edit form by salman
                {
                    model.Form = formManager.GetProjectForm();
                    return View(model);
                }
                try
                {
                    projectManager.UpdateProject(model.ProgramId, model.Project);

                    if (model.ProgramId > 0)
                        return RedirectToAction("Edit", "Program", new { id = model.ProgramId });
                    else
                        return RedirectToAction("Index", "Portfolio");

                }
                catch (Exception e)
                {
                    return View("Error");
                }
                
            }

            return View("Error");
        }

        //
        // GET: /Project/AddTask
        [Authorize(Roles = "admins")]
        public ActionResult AddTask(int projectId)
        {
            var model = CreateViewModel(projectId);

            return View(model);
        }

        //
        // POST: /Project/AddTask
        [HttpPost]
        public ActionResult AddTask([ModelBinder(typeof(ProjectViewModelBinding))] ProjectViewModel model)
        {
            try
            {
                projectManager.AddProjectTask(model.Project.Id, model.Task);

                return RedirectToAction("Edit", new { id = model.Project.Id });
            }
            catch (Exception e)
            {
                return View("Error");
            }
        }

        //
        // GET: /Project/EditTask
        [Authorize(Roles = "admins")]
        public ActionResult EditTask(int Id)
        {
            return View(projectManager.GetProjectTaskById(Id));
        }

        //
        // POST: /Project/EditTask
        [HttpPost]
        public ActionResult EditTask(ProjectTask task)
        {
            try
            {
                var project = projectManager.GetProjectById(task.Project.Id);
                if (project != null)
                {
                    projectManager.UpdateProjectTask(project.Id, task);
                }

                return RedirectToAction("Edit", "Project", new { id = task.Project.Id } );
            }
            catch (Exception e)
            {
                return View("Error");
            }
        }

        //
        // GET: /Project/DeleteTask

        public ActionResult DeleteTask(int id)
        {
            try
            {
                var task = projectManager.GetProjectTaskById(id);
                var project = projectManager.GetProjectById(task.Project.Id);
                if (project != null)
                {
                    projectManager.DeleteProjectTask(project.Id, task);
                }

                return RedirectToAction("Edit", "Project", new { id = project.Id });
            }
            catch (Exception e)
            {
                return View("Error");
            }
        }

        // --------------------------------------
        // Private methods
        // --------------------------------------
        #region Private methods

        /// <summary>
        /// Creates all ProjectDetail objects, that are
        /// missing corresponding to the Project Form.
        /// </summary>
        /// <param name="subproject"></param>
        /// <param name="form"></param>
        private void CreateProjectDetails(Project project, Form form)
        {
            var newDetails = false;

            foreach (var item in form.FormElements)
            {
                var projectDetail = project.GetDetailByName(item.Name);

                if (projectDetail == null)
                {
                    project.AddDetail(item.Name);

                    newDetails = true;
                }
            }

            if (newDetails)
            {
                int programId = 0;
                if (project.Program != null)
                    programId = project.Program.Id;

                projectManager.UpdateProject(programId, project);
            }
        }

        private ProjectViewModel CreateViewModel(int projectId)
        {
            var project = projectManager.GetProjectById(projectId);
            var programId = 0;
            if (project.Program != null)
                programId = project.Program.Id;

            var model = new ProjectViewModel
            {
                ProgramId = programId,
                Project = project,
                Form = formManager.GetProjectForm(),
                Task = new ProjectTask()
            };

            return model;
        }

        #endregion
    }
}
